/**
 * 
 */
package de.cbf.cam.dsa.tavern.carte.model.entities;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

import de.cbf.cam.dsa.tavern.carte.model.entities.interfaces.IEditableEntity;
import de.cbf.cam.dsa.tavern.carte.model.entities.interfaces.INamedEntity;

/**
 * @author Stefan Alter
 *
 */
public class Processing implements INamedEntity,IEditableEntity{
	public static final int PCE_INDEX_NAME					= 2;
	public static final int PCE_INDEX_PRICE					= 3;
	public static final int PCE_INDEX_Addendums				= 4;	
	public static final int PCE_INDEX_ADDENDUMCATEGORIES	= 5;
	
	public final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
	
	private String 					name = "<Neu>";
	private Double					modifiedPrice = 0.0;
	private Collection<Addendum> 	addendums					= new HashSet<Addendum>();
	private Collection<String>		possibleAddendumCategories	= new HashSet<String>();
	
	
	public static Collection<Object> transformIteratorProcessings(
			Iterator<Processing> iterator) {
		Collection<Object> resultList = new ArrayList<Object>();		
		while (iterator.hasNext()) {
			Processing processing = (Processing) iterator.next();
			resultList.add(processing);
		}
		return resultList;	
	}
	
	@Override
	public String toString() {
		return name;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((addendums == null) ? 0 : addendums.hashCode());
		result = prime * result
				+ ((modifiedPrice == null) ? 0 : modifiedPrice.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime
				* result
				+ ((possibleAddendumCategories == null) ? 0
						: possibleAddendumCategories.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Processing other = (Processing) obj;
		if (addendums == null) {
			if (other.addendums != null)
				return false;
		} else if (!addendums.equals(other.addendums))
			return false;
		if (modifiedPrice == null) {
			if (other.modifiedPrice != null)
				return false;
		} else if (!modifiedPrice.equals(other.modifiedPrice))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (possibleAddendumCategories == null) {
			if (other.possibleAddendumCategories != null)
				return false;
		} else if (!possibleAddendumCategories
				.equals(other.possibleAddendumCategories))
			return false;
		return true;
	}
	
	@Override
	public void takeOverValuesFrom(IEditableEntity entity)
			throws IllegalArgumentException {
		if (entity instanceof Processing) {
			Processing processing = (Processing) entity;
			name = processing.name;
			modifiedPrice = processing.modifiedPrice;
			addendums.addAll(processing.addendums);
			possibleAddendumCategories.addAll(processing.possibleAddendumCategories);			
		}else{
			throw new IllegalArgumentException(	"Wrong type provided: "+entity.getClass().getName()+"\n" +
												"Expected: "+Processing.class.getName());
		}
	}

	public Processing clone(){
		Processing processing = new Processing();
		processing.takeOverValuesFrom(this);
		return processing;
	}
	
	@Override
	public PropertyChangeSupport getPropertyChangeSupport() {		
		return propertyChangeSupport;
	}
	
	
	public String getName() {
		return name;
	}
	public void setName(String value) {
		if(value == null || value.equals(name)) return;
		String oldName = this.name;
		this.name = value;
		propertyChangeSupport.fireIndexedPropertyChange("name",PCE_INDEX_NAME,oldName,value);
	}
	
	public Double getModifiedPrice() {
		return modifiedPrice;
	}
	public void setModifiedPrice(Double modifiedPrice) {
		if(this.modifiedPrice.equals(modifiedPrice)) return;
		Double oldPrice = this.modifiedPrice;		
		this.modifiedPrice = modifiedPrice;
		propertyChangeSupport.fireIndexedPropertyChange
		("modifiedPrice",PCE_INDEX_PRICE,oldPrice,modifiedPrice);
	}
	/**
	 * ONLY for XML-Im-/Exporter
	 * @return
	 */
	public Addendum[] getAddendumArray(){
		return addendums.toArray(new Addendum[0]);
	}
	/**
	 * ONLY for XML-Im-/Exporter<br>
	 * for normal access use setAddendums()
	 * @param addendums 
	 */
	public void setAddendumArray(Addendum[] addendums){
		this.addendums.clear();
		for (int i = 0; i < addendums.length; i++) {
			this.addendums.add(addendums[i]);
		}
	}
	public Iterator<Addendum> iteratorAddendums(){
		return addendums.iterator();
	}
	public boolean addAddendum(Addendum addendum){
		if(addendum == null) return false;						
		boolean change = addendums.add(addendum);
		if(change){
			setModifiedPrice(modifiedPrice + addendum.getModifiedPrice());
			propertyChangeSupport.fireIndexedPropertyChange("addendums",PCE_INDEX_Addendums,null,addendums);
		}		
		return change; 
	}
	public boolean removeAddendum(Addendum addendum){
		boolean change = addendums.remove(addendum);
		if(change){
			setModifiedPrice(modifiedPrice - addendum.getModifiedPrice());
			propertyChangeSupport.fireIndexedPropertyChange("addendums",PCE_INDEX_Addendums,null,addendums);			
		}		
		return change;
	}

	public void setAddendums(Collection<Addendum> addendums) {
		if(this.addendums != null && this.addendums.equals(addendums)){ return; }
		Iterator<Addendum> iterator = iteratorAddendums();
		while (iterator.hasNext()) {
			Addendum oldAddendum = (Addendum) iterator.next();
			oldAddendum.propertyChangeSupport.removePropertyChangeListener(pcaAddendums);
		}
		this.addendums.clear();
		if(addendums == null){
			return;
		}
		boolean change = this.addendums.addAll(addendums);		
		if(change){
			iterator = iteratorAddendums();		
			while (iterator.hasNext()) {
				Addendum newAddendum = (Addendum) iterator.next();
				newAddendum.propertyChangeSupport.addPropertyChangeListener(pcaAddendums);
			}
			propertyChangeSupport.fireIndexedPropertyChange(
					"Addendums",PCE_INDEX_Addendums, null,this.addendums);			
		}		
	}
	
	public Iterator<String> iteratorPossibleAddendumCategories(){
		return possibleAddendumCategories.iterator();
	}
	public boolean addPossibleAddendumCategory(String category){
		if(category == null||category.length() == 0) return false;
		boolean change = possibleAddendumCategories.add(category);
		if(change){
			propertyChangeSupport.fireIndexedPropertyChange
			("possibleAddendumCategories",PCE_INDEX_ADDENDUMCATEGORIES,null,possibleAddendumCategories);
		}
		return change; 
	}
	public boolean removePossibleAddendumCategory(String category){
		if(category == null||category.length() == 0) return false;
		boolean change = possibleAddendumCategories.remove(category);
		if(change){
			propertyChangeSupport.fireIndexedPropertyChange
			("possibleAddendumCategories",PCE_INDEX_ADDENDUMCATEGORIES,null,possibleAddendumCategories);
		}
		return change; 
	}
	public void setPossibleAddendumTypes(Collection<String> possibleAddendumCategories) {
		this.possibleAddendumCategories.clear();
		boolean change = this.possibleAddendumCategories.addAll(possibleAddendumCategories);
		if(change){
			propertyChangeSupport.fireIndexedPropertyChange
			("possibleAddendumCategories",PCE_INDEX_ADDENDUMCATEGORIES,null,possibleAddendumCategories);
		}
	}
	
	public String getAddendumsText() {
		StringBuffer buff = new StringBuffer();
		for (Iterator<Addendum> iterator = iteratorAddendums(); iterator.hasNext();) {
			Addendum addendum = (Addendum) iterator.next();
			buff.append(addendum.getName());
			if(iterator.hasNext()){
				buff.append(", ");
			}
		}		
		return buff.toString();
	}
	private PCAdvancerAddendums pcaAddendums = new PCAdvancerAddendums();
	private class PCAdvancerAddendums implements PropertyChangeListener{
		@Override
		public void propertyChange(PropertyChangeEvent event) {
			propertyChangeSupport.fireIndexedPropertyChange(
					event.getPropertyName(),PCE_INDEX_Addendums,null,addendums);
		}		
	}
	
	
	
	
	
}
